package com.dragons.dragonsvf.utils.secret;


import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
//https://zhuanlan.zhihu.com/p/477701164
public class DESEncryption {

//    // 算法名称
//    public static final String KEY_ALGORITHM = "DES";
//    // 算法名称/加密模式/填充方式
//    // DES共有四种工作模式-->>ECB：电子密码本模式、CBC：加密分组链接模式、CFB：加密反馈模式、OFB：输出反馈模式
//    public static final String CIPHER_ALGORITHM = "DES/ECB/NoPadding";
//
//    /**
//     * 生成密钥key对象
//     * @param keyStr 密钥字符串
//     * @return 密钥对象
//     * @throws InvalidKeyException
//     * @throws NoSuchAlgorithmException
//     * @throws InvalidKeySpecException
//     * @throws Exception
//     */
//    private static SecretKey keyGenerator(String keyStr) throws Exception {
//        byte input[] = HexString2Bytes(keyStr);
//        DESKeySpec desKey = new DESKeySpec(input);
//        // 创建一个密匙工厂，然后用它把DESKeySpec转换成
//        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
//        SecretKey securekey = keyFactory.generateSecret(desKey);
//        return securekey;
//    }
//
//    private static int parse(char c) {
//        if (c >= 'a') {
//            return (c - 'a' + 10) & 0x0f;
//        }
//        if (c >= 'A') {
//            return (c - 'A' + 10) & 0x0f;
//        }
//        return (c - '0') & 0x0f;
//    }
//
//    // 从十六进制字符串到字节数组转换
//    public static byte[] HexString2Bytes(String hexstr) {
//        byte[] b = new byte[hexstr.length() / 2];
//        int j = 0;
//        for (int i = 0; i < b.length; i++) {
//            char c0 = hexstr.charAt(j++);
//            char c1 = hexstr.charAt(j++);
//            b[i] = (byte) ((parse(c0) << 4) | parse(c1));
//        }
//        return b;
//    }
//
//    /**
//     * 加密数据
//     * @param data 待加密数据
//     * @param key 密钥
//     * @return 加密后的数据
//     */
//    public static String encrypt(String data, String key) throws Exception {
//        Key deskey = keyGenerator(key);
//        // 实例化Cipher对象，它用于完成实际的加密操作
//        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
//        SecureRandom random = new SecureRandom();
//        // 初始化Cipher对象，设置为加密模式
//        cipher.init(Cipher.ENCRYPT_MODE, deskey, random);
//        byte[] results = cipher.doFinal(data.getBytes());
//        // 该部分是为了与加解密在线测试网站（http://tripledes.online-domain-tools.com/）的十六进制结果进行核对
//        for (int i = 0; i < results.length; i++) {
//            System.out.print(results[i] + " ");
//        }
//        System.out.println();
//        // 执行加密操作。加密后的结果通常都会用Base64编码进行传输
//        return Base64.encodeBase64String(results);
//    }
//
//    /**
//     * 解密数据
//     * @param data 待解密数据
//     * @param key 密钥
//     * @return 解密后的数据
//     */
//    public static String decrypt(String data, String key) throws Exception {
//        Key deskey = keyGenerator(key);
//        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
//        // 初始化Cipher对象，设置为解密模式
//        cipher.init(Cipher.DECRYPT_MODE, deskey);
//        // 执行解密操作
//        return new String(cipher.doFinal(Base64.decodeBase64(data)));
//    }
//
//    public static void main(String[] args) throws Exception {
//        String source = "helloittx";
//        System.out.println("原文: " + source);
//        String key = "A1B2C3D4";
//        String encryptData = encrypt(source, key);
//        System.out.println("加密后: " + encryptData);
//        String decryptData = decrypt(encryptData, key);
//        System.out.println("解密后: " + decryptData);
//    }

    /***
     对称加密

     对称加密是最快速、最简单的一种加密方式， 加密（encryption）与解密（decryption）用的是同样的密钥（secret key） 。对称加密有很多种算法，由于它效率很高，所以被广泛使用在很多加密协议的核心当中。

     对称加密通常使用的是相对较小的密钥，一般小于256 bit。因为密钥越大，加密越强，但加密与解密的过程越慢。如果你只用1 bit来做这个密钥，那黑客们可以先试着用0来解密，不行的话就再用1解；
     但如果你的密钥有1 MB大，黑客们可能永远也无法破解，但加密和解密的过程要花费很长的时间。密钥的大小既要照顾到安全性，也要照顾到效率，是一个trade-off。

     DES (Data Encryption Standard)和 TripleDES 是对称加密的两种实现。

     DES和TripleDES基本算法一致，只是TripleDES算法提供的key位数更多，加密可靠性更高。

     DES使用的密钥key为8字节，初始向量IV也是8字节。

     TripleDES使用24字节的key，初始向量IV也是8字节。

     两种算法都是以8字节为一个块进行加密，一个数据块一个数据块的加密，一个8字节的明文加密后的密文也是8字节。如果明文长度不为8字节的整数倍，添加值为0的字节凑满8字节整数倍。所以加密后的密文长度一定为8字节的整数倍
     */

    public static void main(String[] args) throws Exception {
        String plainText = "Hello, World!";
        String key = "12345678"; // DES密钥长度为8字节

        // 加密
        byte[] encryptedData = encrypt(plainText, key);
        System.out.println("Encrypted data: " + Base64.getEncoder().encodeToString(encryptedData));

        // 解密
        String decryptedText = decrypt(encryptedData, key);
        System.out.println("Decrypted text: " + decryptedText);
    }

    public static byte[] encrypt(String plainText, String key) throws Exception {
        DESKeySpec desKeySpec = new DESKeySpec(key.getBytes(StandardCharsets.UTF_8));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);

        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        return cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
    }

    public static String decrypt(byte[] encryptedData, String key) throws Exception {
        DESKeySpec desKeySpec = new DESKeySpec(key.getBytes(StandardCharsets.UTF_8));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey secretKey = keyFactory.generateSecret(desKeySpec);

        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decryptedData = cipher.doFinal(encryptedData);
        return new String(decryptedData, StandardCharsets.UTF_8);
    }
}
